<template>
  <div class="qa-page">
    <el-row :gutter="20">
      <el-col :lg="10" :md="11" :sm="24" :xs="24">
        <el-card class="qa-card" shadow="hover">
          <template #header>
            <div class="card-header">
              <div class="card-heading">
                <el-icon class="heading-icon"><ChatLineRound /></el-icon>
                <div>
                  <h3>智能问答助手</h3>
                  <p>结合中西医智慧，为您提供专业建议</p>
                </div>
              </div>
              <el-tag type="success" effect="plain">实时 · DeepSeek</el-tag>
            </div>
          </template>
          <el-form ref="formRef" :model="form" :rules="rules" label-position="top">
            <el-form-item label="问答类型" prop="type">
              <el-segmented v-model="form.type" :options="typeOptions" size="large" class="type-segment" />
            </el-form-item>
            <el-form-item label="请输入您的问题" prop="content">
              <el-input
                v-model="form.content"
                type="textarea"
                :rows="8"
                maxlength="2000"
                show-word-limit
                placeholder="例如：最近总是感觉口干舌燥伴有睡眠不佳，请问如何调理？"
              />
            </el-form-item>
            <div class="form-actions">
              <el-button type="primary" :loading="submitting" @click="handleSubmit">
                <el-icon class="submit-icon"><Promotion /></el-icon>
                提交并获取建议
              </el-button>
              <el-button link type="info" @click="resetForm" :disabled="submitting">重置</el-button>
            </div>
          </el-form>
          <transition name="fade">
            <el-card v-if="streaming" class="streaming-card" shadow="never">
              <div class="streaming-header">
                <el-icon class="streaming-icon"><Promotion /></el-icon>
                <span>AI 正在生成建议...</span>
              </div>
              <el-scrollbar max-height="180px" class="streaming-content">
                <p v-if="streamingAnswer" class="streaming-text">{{ streamingAnswer }}</p>
                <el-skeleton v-else animated :rows="3" />
              </el-scrollbar>
            </el-card>
          </transition>
          <el-alert
            show-icon
            type="info"
            :closable="false"
            title="说明"
            description="升级后已接入 DeepSeek Reasoner 模型，数据仅供健康参考，不可替代医师诊断。"
            class="info-alert"
          />
        </el-card>
      </el-col>
      <el-col :lg="14" :md="13" :sm="24" :xs="24">
        <el-card class="qa-history" shadow="hover">
          <template #header>
            <div class="history-header">
              <h3>问答记录</h3>
              <el-select v-model="filter.type" placeholder="全部类型" clearable size="small" @change="loadQuestions">
                <el-option label="全部类型" :value="undefined" />
                <el-option v-for="option in typeOptions" :key="option.value" :label="option.label" :value="option.value" />
              </el-select>
            </div>
          </template>
          <el-empty v-if="!loading && questions.length === 0" description="还没有提问，快来体验智能问答吧" />
          <el-skeleton v-else :loading="loading" animated :rows="4">
            <el-timeline class="qa-timeline">
              <el-timeline-item
                v-for="item in questions"
                :key="item.id"
                :timestamp="formatTime(item.createdAt)"
                placement="top"
              >
                <el-card shadow="never" class="timeline-card">
                  <div class="timeline-header">
                    <el-tag :type="typeTag(item.type)" size="small" effect="dark">
                      {{ typeLabel(item.type) }}
                    </el-tag>
                    <span class="confidence">信心指数：{{ formatConfidence(item.confidence) }}</span>
                  </div>
                  <div class="question-block">
                    <p class="label">问题</p>
                    <p class="content">{{ item.content }}</p>
                  </div>
                  <div class="answer-block">
                    <p class="label">智能回答</p>
                    <p class="content">{{ item.answer }}</p>
                  </div>
                </el-card>
              </el-timeline-item>
            </el-timeline>
          </el-skeleton>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue';
import dayjs from 'dayjs';
import type { FormInstance, FormRules } from 'element-plus';
import { ElMessage } from 'element-plus';
import { ChatLineRound, Promotion } from '@element-plus/icons-vue';
import { fetchQuestions } from '@/api/questions';
import { useAuthStore } from '@/store/modules/auth';
import type { QuestionCreatePayload, QuestionItem, QuestionType } from '@/types/question';

const formRef = ref<FormInstance>();
const submitting = ref(false);
const loading = ref(false);
const questions = ref<QuestionItem[]>([]);
const streaming = ref(false);
const streamingAnswer = ref('');
const streamController = ref<AbortController | null>(null);
const baseApi = import.meta.env.VITE_API_BASE_URL || '/api';
const authStore = useAuthStore();

const form = reactive<QuestionCreatePayload>({
  content: '',
  type: 'HYBRID',
});

const rules: FormRules<QuestionCreatePayload> = {
  content: [{ required: true, message: '请输入您的问题', trigger: 'blur' }],
  type: [{ required: true, message: '请选择问答类型', trigger: 'change' }],
};

const typeOptions = [
  { label: '中医问诊', value: 'TCM' as QuestionType },
  { label: '西医问诊', value: 'WESTERN' as QuestionType },
  { label: '中西结合', value: 'HYBRID' as QuestionType },
];

const filter = reactive<{ type?: QuestionType }>({ type: undefined });

const typeLabel = (value: QuestionType) => typeOptions.find((option) => option.value === value)?.label ?? value;

const typeTag = (value: QuestionType) => {
  switch (value) {
    case 'TCM':
      return 'success';
    case 'WESTERN':
      return 'info';
    case 'HYBRID':
    default:
      return 'warning';
  }
};

const formatConfidence = (value: number) => `${(value * 100).toFixed(0)}%`;

const formatTime = (time: string) => dayjs(time).format('YYYY/MM/DD HH:mm');

const loadQuestions = async () => {
  loading.value = true;
  try {
    questions.value = await fetchQuestions({ type: filter.type, page: 1, size: 20 });
  } finally {
    loading.value = false;
  }
};

const handleSubmit = () => {
  formRef.value?.validate(async (valid) => {
    if (!valid) return;
    submitting.value = true;
    streaming.value = true;
    streamingAnswer.value = '';
    try {
      const controller = new AbortController();
      streamController.value = controller;
      const headers: Record<string, string> = { 'Content-Type': 'application/json' };
      const token = authStore.token ?? localStorage.getItem('tcm-ai-token');
      if (token) {
        headers.Authorization = token.startsWith('Bearer ') ? token : `Bearer ${token}`;
      }

      const response = await fetch(`${baseApi}/v1/questions/stream`, {
        method: 'POST',
        headers,
        body: JSON.stringify(form),
        signal: controller.signal,
      });
      if (!response.ok || !response.body) {
        if (response.status === 401) {
          ElMessage.error('登录状态已过期，请重新登录');
          authStore.clearAuth();
          window.location.href = '/login';
        }
        throw new Error('AI 接口请求失败');
      }

      const reader = response.body.getReader();
      const decoder = new TextDecoder('utf-8');
      let buffer = '';
      let completed = false;

      const flushBuffer = () => {
        let boundary = buffer.indexOf('\n\n');
        while (boundary !== -1) {
          const rawEvent = buffer.slice(0, boundary).trim();
          buffer = buffer.slice(boundary + 2);
          boundary = buffer.indexOf('\n\n');
          if (!rawEvent) continue;
          const lines = rawEvent.split('\n');
          for (const line of lines) {
            if (!line.startsWith('data:')) continue;
            const data = line.slice(5).trim();
            if (!data || data === '[DONE]') continue;
            try {
              const payload = JSON.parse(data) as {
                content?: string;
                finished?: boolean;
                confidence?: number;
                record?: QuestionItem;
              };
              if (payload.finished) {
                completed = true;
                if (payload.content) {
                  streamingAnswer.value = payload.content;
                }
                if (payload.record) {
                  questions.value = [payload.record, ...questions.value].slice(0, 50);
                } else {
                  loadQuestions();
                }
                ElMessage.success('智能建议已生成');
              } else if (payload.content) {
                streamingAnswer.value += payload.content;
              }
            } catch (err) {
              console.warn('解析流式数据失败', err);
            }
          }
        }
      };

      while (true) {
        const { value, done } = await reader.read();
        if (done) break;
        buffer += decoder.decode(value, { stream: true });
        flushBuffer();
      }
      flushBuffer();
      if (!completed) {
        ElMessage.warning('AI 未完成回答，请稍后重试');
      }
      form.content = '';
    } catch (error) {
      console.error(error);
      ElMessage.error((error as Error).message || '生成智能建议失败');
    } finally {
      streamController.value = null;
      submitting.value = false;
      streaming.value = false;
    }
  });
};

const resetForm = () => {
  if (streamController.value) {
    streamController.value.abort();
    streamController.value = null;
  }
  streaming.value = false;
  streamingAnswer.value = '';
  formRef.value?.resetFields();
};

onMounted(loadQuestions);
</script>

<style scoped lang="scss">
.qa-page {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.qa-card,
.qa-history {
  border-radius: 16px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-heading {
  display: flex;
  align-items: center;
  gap: 1rem;

  h3 {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 600;
    color: #1f2937;
  }

  p {
    margin: 0.25rem 0 0;
    color: #6b7280;
  }
}

.heading-icon {
  font-size: 2.4rem;
  color: #2563eb;
}

.type-segment {
  width: 100%;
}

.form-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
}

.submit-icon {
  margin-right: 0.25rem;
}

.streaming-card {
  margin-bottom: 1rem;
  border: 1px solid #bfdbfe;
  background: rgba(59, 130, 246, 0.08);
}

.streaming-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
  color: #1d4ed8;
  margin-bottom: 0.5rem;
}

.streaming-icon {
  font-size: 1.1rem;
}

.streaming-content {
  background: rgba(255, 255, 255, 0.65);
  border-radius: 8px;
  padding: 0.5rem 0.75rem;
  color: #1f2937;
}

.streaming-text {
  white-space: pre-wrap;
  line-height: 1.6;
}

.info-alert {
  margin-top: 0.75rem;
}

.history-header {
  display: flex;
  justify-content: space-between;
  align-items: center;

  h3 {
    margin: 0;
    font-size: 1.2rem;
    font-weight: 600;
    color: #1f2937;
  }
}

.qa-timeline {
  max-height: 640px;
  overflow-y: auto;
  padding-right: 0.5rem;
}

.timeline-card {
  border-radius: 12px;
  border: 1px solid #e5e7eb;
  background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
}

.timeline-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.75rem;
}

.confidence {
  color: #1d4ed8;
  font-weight: 500;
}

.question-block,
.answer-block {
  margin-bottom: 0.75rem;

  .label {
    margin: 0 0 0.4rem;
    font-size: 0.85rem;
    color: #64748b;
    letter-spacing: 0.08em;
  }

  .content {
    margin: 0;
    color: #1f2937;
    line-height: 1.6;
  }
}

@media screen and (max-width: 768px) {
  .qa-timeline {
    max-height: none;
  }
}
</style>

